package com.jd.jstable.strategy.zookeeper;

import com.alibaba.fastjson.JSON;
import com.jd.jstable.config.KeyMaker;
import com.jd.jstable.config.KeyMode;
import com.jd.jstable.strategy.ResetableStrategy;
import com.jd.jstable.strategy.ResultOrientedStrategy;
import com.jd.jstable.strategy.StrategyUtil;
import com.jd.jstable.utils.ZooKeeperUtil;
import org.I0Itec.zkclient.ZkClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.zookeeper.CreateMode;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Method;

/**
 * 这个是用Zookeeper作为结果储存器的策略
 * Created by chenyipu on 2018/4/2.
 */
@Service("MD5_138cc4666fbd6262a0a57cab833c5dbc_zookeeper")
public class ZooKeeperStrategy extends ResultOrientedStrategy implements ResetableStrategy, KeyMaker {
    private final static String zkPath = "/jstable/strategy";
    private static final Log logger = LogFactory.getLog(ZooKeeperStrategy.class);

    @Resource
    ZkClient jstableZkClient;

    @Override
    public void feed(Object invoker, Method method, Object[] args, Object result, String param, KeyMode keyMode) {
        if(jstableZkClient==null){
            return;
        }
        //set the path and bind the value
        ZooKeeperUtil.createRecursively(jstableZkClient, String.format("%s/%s", zkPath, keyMode.getPrefix()));
        String key = generate(invoker, method, args, keyMode);
        set(key, JSON.toJSONString(result));
    }

    @Override
    public Object solve(Object invoker, Method method, Object[] args, String param, KeyMode keyMode) {
        //get value from the path
        if(jstableZkClient==null){
            return null;
        }
        String key = generate(invoker, method, args, keyMode);
        return JSON.parseObject(get(key), method.getReturnType());
    }

    private void set(String path, String data) {
        try {
            jstableZkClient.writeData(path, data);
        }
        catch (Exception e){
            jstableZkClient.create(path, data, CreateMode.PERSISTENT);
        }
    }

    private String get(String path) {
        try {
            return jstableZkClient.readData(path);
        }
        catch (Exception e){
            logger.error(e);
            return null;
        }
    }

    @Override
    public String generate(Object invoker, Method method, Object[] args, KeyMode keyMode) {
        return String.format("%s/%s/%s", zkPath, keyMode.getPrefix(), StrategyUtil.makeResourceKeyMd5(invoker.getClass(), method.getName(), args, keyMode));
    }

    @Override
    public void reset(Object invoker, Method method, Object[] args, String param, KeyMode keyMode) {
        String key = generate(invoker, method, args, keyMode);
        jstableZkClient.deleteRecursive(key);
    }
}
